Skip to content

feat(prisma-next)!: make the adapter EQL v3 only (fixes Supabase superuser block, #709)#712

Merged
coderdan merged 3 commits into
mainfrom
fix/prisma-next-v3-only-install
Jul 21, 2026
Merged

feat(prisma-next)!: make the adapter EQL v3 only (fixes Supabase superuser block, #709)#712
coderdan merged 3 commits into
mainfrom
fix/prisma-next-v3-only-install

Conversation

@coderdan

@coderdan coderdan commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Makes @cipherstash/prisma-next EQL v3 only — the install path, the authoring constructors, the runtime codecs, and the v2 subpath exports are all removed. This fixes the rc.3 skilltester F3 blocker: the adapter was unusable on Supabase because prisma-next migration apply installed the EQL v2 bundle, whose install requires a Postgres superuser.

Closes #709.

Root cause (install path)

The v2 and v3 baselines were chained: the v3 migration edge started from the v2 baseline's to state, and refs/head.json required both invariants. So on a fresh database the only path to head ran the v2 install first — and the v2 bundle fails on Supabase's non-superuser postgres role, even for a pure-v3 app. (#694 only changed how the v3 baseline sources its SQL; it never removed v2 from the apply path.)

Fix: the v3 baseline is re-rooted as an invariant-only genesis edge (from: null), the contract models no storage (the eql_v2_configuration table is gone), and the head ref requires only cipherstash:install-eql-v3-bundle-v1. Contract-space artefacts are re-emitted (contract.json, head.json, the v3 migration.json). prisma-next migration apply now installs only EQL v3 and works on Supabase as a non-superuser.

Breaking — API removed

  • Client: cipherstashFromStackV2, deriveStackSchemas, createCipherstashSdk (from ./stack) → use cipherstashFromStack (v3).
  • Authoring: the encrypted*V2 TS factories and cipherstash.Encrypted*V2 PSL constructors → use the v3 domain factories/constructors (text / textSearch / bigIntOrd / … and cipherstash.TextSearch() etc.).
  • Runtime: the v2 codecs, createCipherstashRuntimeDescriptor, the cipherstash* operators/helpers, and the EncryptedDouble envelope → use the v3 runtime (createCipherstashV3RuntimeDescriptor, bulkEncryptMiddlewareV3, the eql* operators, EncryptedNumber).
  • Subpaths: ./middleware and ./migration removed.

Kept: the version-neutral value envelopes (EncryptedString/BigInt/Boolean/Date/Json) and decryptAll — the v3 surface is unchanged. The one shared v2→v3 edge, stampRoutingKeysFromAst, was moved into execution/routing so src/middleware/ could be deleted.

Scale

~19,900 lines removed across 45 deleted files (the bulk is the baked v2 install SQL + the v2 codec/authoring/runtime layer). Two changesets: @cipherstash/prisma-next minor + a stash patch for the bundled stash-prisma-next skill.

Validation

  • 320/320 unit tests pass (33 files); typecheck clean; build clean (ESM + DTS); bundling-isolation green against fresh dist; 0 biome errors.
  • Framework-integrity gates hold: assertDescriptorSelfConsistency and the materialise→disk→integrity-read round-trip.
  • No external consumer (examples, e2e) imports a removed symbol.

Docs

README subpath table, the stash-prisma-next skill, the AGENTS.md repository layout, and the prisma example JSDoc are updated; DEVELOPING.md is rewritten for the v3 architecture (catalog-derived domains, the eql* surface, the query-term seam, the genesis-edge migration).

One thing to note — now resolved

isBulkEncryptMiddlewareRegistered in execution/middleware-registry.ts was
marked-but-never-read: the RUNTIME.ENCODE_FAILED "middleware not wired" guard
lived in the v2 cell-codec-factory.ts (deleted here), and v3 never wired one.
Rather than leave the registry as dead weight, the guard is now ported to
CipherstashV3CellCodec#encode
— an SDK with no bulkEncryptMiddlewareV3(sdk)
registered fails fast with a copy-pasteable wiring snippet instead of an opaque
pg serialise error. Memoised per codec (the registry is add-only), so it costs
one WeakSet lookup, not one per cell. Two new tests cover it; DEVELOPING.md
and the changeset are updated to match.

Review note

Two commits: the code change, then docs. Not split into "install-path" vs "code-removal" because control.ts carries both and patch-level staging wasn't available in the automation environment — splitting risked a non-building intermediate commit.

Summary by CodeRabbit

  • Breaking Changes
    • Prisma Next now supports EQL v3 only; regenerate contracts before upgrading.
    • Removed legacy v2 constructors, operators, runtime APIs, middleware, migration helpers, and subpath exports.
    • Replaced EncryptedDouble with EncryptedNumber.
  • New Features
    • Added v3 domain-specific encrypted column factories and eql* query operators.
    • Added v3 runtime, middleware, driver adapters, and one-call stack setup.
  • Documentation
    • Updated guides, examples, and bundled skill documentation for the v3-only workflow.

Summary by CodeRabbit

  • Breaking Changes

    • Prisma Next now supports EQL v3 exclusively; legacy v2 constructors, operators, runtime APIs, middleware, and migration exports have been removed.
    • Existing contracts should be regenerated using the v3 domain constructors and eql* operators.
  • New Features

    • Added v3 typed column factories, runtime descriptor APIs, and bulkEncryptMiddlewareV3.
    • EQL v3 migrations now install exclusively, including for managed Postgres environments.
  • Bug Fixes

    • Missing bulk-encrypt middleware now produces an actionable RUNTIME.ENCODE_FAILED diagnostic.
  • Documentation

    • Updated guides, examples, and bundled skill instructions for the v3-only experience.

coderdan added 2 commits July 20, 2026 21:58
Remove the EQL v2 surface from `@cipherstash/prisma-next` entirely — the
install path, the authoring constructors, the runtime codecs, and the v2
subpath exports — so the adapter installs only EQL v3 and works on managed
Postgres (e.g. Supabase) as a non-superuser.

Install path (the root cause of the Supabase block):
- Re-root the v3 baseline migration as an invariant-only genesis edge
  (`from: null`); the contract now models no storage; the head ref requires
  only `cipherstash:install-eql-v3-bundle-v1`. The v2 and v3 baselines were
  chained (v3 started from v2's `to` state, head required both invariants),
  so `migration apply` always ran the v2 install first — which fails on a
  non-superuser role. Re-emit the contract-space artefacts.
- Delete the v2 baseline migration (`20260601T0000_install_eql_bundle`).

API/code removal:
- Delete the v2 authoring/runtime/codec code: `cipherstashFromStackV2`,
  the `*V2` constructors, the v2 codec runtime + composite wire, the baked
  `eql-install.generated`, and the v2 codec-control hooks.
- Remove the `./middleware` and `./migration` subpath exports.
- Move the version-neutral `stampRoutingKeysFromAst` into `execution/routing`
  so `src/middleware/` can be removed; keep the shared value envelopes
  (`EncryptedString`/`BigInt`/`Boolean`/`Date`/`Json`) and `decryptAll`. The
  v3 surface is unchanged.

Prune the v2 tests and update the shared/v3 tests (descriptor, migration,
bundling-isolation, operator/type gating) for the v3-only reality.

Refs #709
…3-only

Rewrite `DEVELOPING.md` for the v3 architecture (catalog-derived domains,
the `eql*` operator surface, the query-term seam, the genesis-edge
migration) and match this repo's actual `src/` layout. Drop the removed v2
surface from the README subpath table, the bundled `stash-prisma-next`
skill, the `AGENTS.md` repository layout, and the prisma example JSDoc.

Refs #709
@coderdan
coderdan requested a review from a team as a code owner July 20, 2026 11:59
@changeset-bot

changeset-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9314afb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@cipherstash/prisma-next Minor
stash Minor
@cipherstash/prisma-next-example Patch
@cipherstash/basic-example Patch
@cipherstash/e2e Patch
@cipherstash/stack Minor
@cipherstash/stack-drizzle Minor
@cipherstash/stack-supabase Minor
@cipherstash/wizard Minor
@cipherstash/bench Patch
@cipherstash/test-kit Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

@cipherstash/prisma-next becomes EQL v3-only: the v2 migration, contract storage, APIs, runtime modules, operators, envelopes, and subpath exports are removed. The v3 migration is re-rooted as the sole genesis edge, with updated runtime validation, tests, and documentation.

Changes

Prisma Next EQL v3-only transition

Layer / File(s) Summary
V3 genesis migration and empty contract
packages/prisma-next/migrations/..., packages/prisma-next/src/contract.*, packages/prisma-next/src/exports/control.ts
The v3 migration becomes the sole invariant-only genesis edge, and generated contract storage no longer models the v2 configuration table.
V3 authoring and runtime exports
packages/prisma-next/src/contract-authoring.ts, packages/prisma-next/src/exports/*, packages/prisma-next/src/extension-metadata/*, packages/prisma-next/src/types/*
Legacy v2 constructors, codecs, operators, envelopes, metadata, and stack exports are removed; catalog-derived v3 factories, runtime descriptors, envelopes, and eql* operations remain.
V3 query terms and write routing
packages/prisma-next/src/execution/routing.ts, packages/prisma-next/src/v3/*
Routing keys are stamped from lowered ASTs, v3 middleware uses the routing helper, and encoding validates middleware registration before the write path proceeds.
V3 validation and guidance
packages/prisma-next/test/*, packages/prisma-next/DEVELOPING.md, packages/prisma-next/README.md, skills/stash-prisma-next/SKILL.md
Tests, bundling checks, package metadata, documentation, examples, changesets, and skill guidance are updated for the v3-only surface.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

  • #709 — Directly tracks removing the EQL v2 baseline and making the v3 migration the sole install path.
  • #707 — Covers the related repo-wide EQL v2 removal and v3 migration re-baselining.
  • #717 — Covers the related v3 authoring API renames and cleanup.

Possibly related PRs

Suggested reviewers: calvinbrewer

Sequence Diagram(s)

sequenceDiagram
  participant PrismaNext
  participant CodecRuntime
  participant BulkEncryptMiddlewareV3
  participant CipherstashSdk
  PrismaNext->>CodecRuntime: encode encrypted envelope
  CodecRuntime->>BulkEncryptMiddlewareV3: validate middleware registration
  BulkEncryptMiddlewareV3->>BulkEncryptMiddlewareV3: stamp table and column routing keys
  BulkEncryptMiddlewareV3->>CipherstashSdk: bulkEncrypt plaintext targets
  CipherstashSdk-->>BulkEncryptMiddlewareV3: return ciphertext
  BulkEncryptMiddlewareV3-->>PrismaNext: rewrite parameter to v3 wire format
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR removes the v2 baseline and v2 surfaces, re-roots v3 as the genesis edge, updates head invariants, and refreshes docs/tests/skill as required by #709.
Out of Scope Changes check ✅ Passed No unrelated changes stand out; the docs, tests, config, and runtime updates all support the v3-only migration and API cleanup.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: making prisma-next EQL v3 only and tying it to the Supabase blocker.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/prisma-next-v3-only-install

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@freshtonic freshtonic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

Makes @cipherstash/prisma-next EQL v3 only — removing the v2 install path, authoring constructors, runtime codecs, and the ./middleware / ./migration subpath exports (~20k lines deleted across 45 files). The behavioural fix for the rc.3 F3 Supabase blocker: the v2 and v3 baselines were chained, so a fresh DB ran the v2 install first, and the v2 bundle needs a Postgres superuser — unusable on Supabase even for a pure-v3 app. The v3 baseline is re-rooted as an invariant-only genesis edge and the head ref now requires only the v3 bundle.

This is a large but overwhelmingly subtractive change, and it's internally consistent. Approving.

What I verified

Migration graph re-rooting (the actual fix) — coherent. Traced the content-addressed graph on the branch:

  • refs/head.json now requires exactly one invariant, cipherstash:install-eql-v3-bundle-v1 (the v2 install-eql-bundle-v1 invariant is gone), at hash efd408…431d51e.
  • The old v2 edge 20260601T0000_install_eql_bundle/ is fully deleted (all five artefacts), not left dangling.
  • The v3 edge 20260601T0100_install_eql_v3_bundle/migration.json is re-rooted from: null → to: efd408…431d51e (was a self-loop off the v2 baseline hash); migration.ts describe() matches.
  • Exactly one path reaches head: genesis (from: null) → install-eql-v3-bundle → head, installing only v3. No orphaned edges.
  • contract.prisma/contract.json model no storage (EqlV2Configuration/eql_v2_configuration removed as a model; only narrative prose mentions it). All four content hashes agree end-to-end (head.json hash = v3 migration.json to = v3 end-contract.json storageHash = src/contract.json storageHash = efd408…431d51e), so the modelled contract matches the edge's end state and head is reachable.

Control plane / exports — coherent. control.ts drops the v2 baseline migration and the six v2 codec-control hooks from the contract space, leaving only the v3 genesis edge and cipherstashV3CodecControlHooks (identity expandNativeType, no onFieldEvent — so v3 columns emit no add_search_config/remove_search_config, correct for domain-typed columns). package.json and tsup.config.ts drop ./middleware and ./migration in lockstep; exports/stack.ts and exports/runtime.ts are reduced cleanly to the v3 surface; exports/migration.ts and exports/middleware.ts are deleted. The shared stampRoutingKeysFromAst is moved into execution/routing.ts with proper value imports (EncryptedEnvelopeBase, setHandleRoutingKey) so src/middleware/ could be deleted.

Changesets — correct. @cipherstash/prisma-next minor + stash patch (for the bundled skill). The repo is in changesets prerelease mode (.changeset/pre.json, tag rc), and prisma-next is 1.0.0-rc.3, so minor for a pre-GA breaking change is consistent with the whole EQL-v3 rc train — major would wrongly imply 2.0.0. The ! breaking marker in the title + the detailed breaking-change changeset body cover the migration guidance.

Meta files & docs — updated in-PR (as the repo requires): AGENTS.md repository layout now reads "EQL v3 only", the prisma example JSDoc drops the stale v2 note, README/DEVELOPING/skill rewritten for v3.

No dangling references — verified across the whole branch. For every removed symbol (cipherstashFromStackV2, deriveStackSchemas, createCipherstashSdk, createCipherstashRuntimeDescriptor, the v2 cipherstash* operators, the encrypted*V2/Encrypted*V2 factories, EncryptedDouble) and every removed subpath (./middleware, ./migration), there are zero surviving imports or usages in packages/** (including cross-package), examples/, or e2e/ — the names now appear only in doc comments and CHANGELOG history. The ./middleware//migration hits that remain are upstream Prisma-Next framework subpaths (@prisma-next/postgres/migration, etc.), not the removed local ones. Every package.json export and tsup entry resolves to an existing source file. (Note: @cipherstash/prisma-next was already ESM-only at the merge base — no require/CJS entries to preserve — so the repo's "don't drop CJS" rule doesn't apply here.)

Notes — non-blocking

  1. Acknowledged dead code: isBulkEncryptMiddlewareRegistered in execution/middleware-registry.ts is now marked-but-never-read — v3's encode never wired the "middleware not registered" diagnostic that consulted it (that guard lived in the deleted v2 codec). The PR documents this honestly and defers it. Fine to leave, but the registry + its populate path is now dead weight; a follow-up should either wire a v3 diagnostic or delete the registry.

  2. Two stale doc comments name removed symbols (comment-accuracy only, nothing compiles against them): src/v3/runtime-v3.ts:4 still references createCipherstashRuntimeDescriptor (the live export is createCipherstashV3RuntimeDescriptor), and test/v3/from-stack-v3.test.ts:9 describes the v2 cipherstashFromStackV2 as "a separate, untouched" surface when v2 was in fact deleted. Trivial to fix in passing.

  3. Single squashed code commit. The install-path change and the ~20k-line v2 removal share control.ts, so they're in one commit rather than split. The author explains patch-level staging wasn't available and splitting risked a non-building intermediate. Reasonable given the tooling constraint; noting only.

Verdict

Approve. The behavioural fix is exactly right — re-rooting to a v3-only genesis edge removes the v2 install (and its superuser requirement) from the apply path, and the content-addressed graph, contract artefacts, and head ref are all hash-consistent. The API/subpath removal is complete and leaves no dangling references anywhere in the tree, examples, or e2e. Meta files, docs, and changesets are updated per repo policy. The three notes are all non-blocking follow-ups (dead registry, two stale comments, commit granularity).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/prisma-next/README.md (1)

81-81: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use eqlMatch in this example. cipherstashIlike is legacy v2 syntax; this v3 README should show the free-text search operator used elsewhere here (eqlMatch).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/prisma-next/README.md` at line 81, Update the README query example
to replace the legacy cipherstashIlike operator with eqlMatch, matching the v3
free-text search syntax used elsewhere in the document.

Source: Coding guidelines

🧹 Nitpick comments (1)
packages/prisma-next/migrations/20260601T0100_install_eql_v3_bundle/migration.ts (1)

55-66: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rationale is accurate; align the neighbouring "self-edge" wording.

The data-class justification here now describes a genesis edge (from: null → empty-storage hash), but the adjacent comment at Line 74–75 still says "this is an invariant-only self-edge." Since you retired the "self-edge" framing in this block, update that trailing comment too so the file's genesis-vs-self classification is consistent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/prisma-next/migrations/20260601T0100_install_eql_v3_bundle/migration.ts`
around lines 55 - 66, Update the adjacent trailing comment near operationClass
in the migration definition to remove the outdated “self-edge” wording and
describe the edge consistently as a genesis/no-storage-movement edge, preserving
its invariant-only meaning.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/prisma-next/README.md`:
- Line 13: Remove the outdated “legacy v2 surface keeps its cipherstash* names”
clause from the type-safe query operators bullet in the README, leaving only the
current EQL v3 operator vocabulary. Ensure nearby README references consistently
omit the removed EQL v2 surface and reflect the current package exports.

---

Outside diff comments:
In `@packages/prisma-next/README.md`:
- Line 81: Update the README query example to replace the legacy
cipherstashIlike operator with eqlMatch, matching the v3 free-text search syntax
used elsewhere in the document.

---

Nitpick comments:
In
`@packages/prisma-next/migrations/20260601T0100_install_eql_v3_bundle/migration.ts`:
- Around line 55-66: Update the adjacent trailing comment near operationClass in
the migration definition to remove the outdated “self-edge” wording and describe
the edge consistently as a genesis/no-storage-movement edge, preserving its
invariant-only meaning.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5d4d7fb6-11e1-41c8-8ac3-04d1287b3492

📥 Commits

Reviewing files that changed from the base of the PR and between 4888995 and 8e7127a.

⛔ Files ignored due to path filters (1)
  • packages/prisma-next/src/migration/eql-install.generated.ts is excluded by !**/*.generated.*
📒 Files selected for processing (94)
  • .changeset/prisma-next-v3-only-install.md
  • .changeset/stash-prisma-next-skill-v3-only.md
  • AGENTS.md
  • examples/prisma/src/db.ts
  • packages/prisma-next/DEVELOPING.md
  • packages/prisma-next/README.md
  • packages/prisma-next/migrations/20260601T0000_install_eql_bundle/end-contract.d.ts
  • packages/prisma-next/migrations/20260601T0000_install_eql_bundle/end-contract.json
  • packages/prisma-next/migrations/20260601T0000_install_eql_bundle/migration.json
  • packages/prisma-next/migrations/20260601T0000_install_eql_bundle/migration.ts
  • packages/prisma-next/migrations/20260601T0000_install_eql_bundle/ops.json
  • packages/prisma-next/migrations/20260601T0100_install_eql_v3_bundle/end-contract.d.ts
  • packages/prisma-next/migrations/20260601T0100_install_eql_v3_bundle/end-contract.json
  • packages/prisma-next/migrations/20260601T0100_install_eql_v3_bundle/migration.json
  • packages/prisma-next/migrations/20260601T0100_install_eql_v3_bundle/migration.ts
  • packages/prisma-next/migrations/refs/head.json
  • packages/prisma-next/package.json
  • packages/prisma-next/src/contract-authoring.ts
  • packages/prisma-next/src/contract.d.ts
  • packages/prisma-next/src/contract.json
  • packages/prisma-next/src/contract.prisma
  • packages/prisma-next/src/execution/cell-codec-factory.ts
  • packages/prisma-next/src/execution/codec-runtime.ts
  • packages/prisma-next/src/execution/envelope-base.ts
  • packages/prisma-next/src/execution/envelope-double.ts
  • packages/prisma-next/src/execution/helpers.ts
  • packages/prisma-next/src/execution/middleware-registry.ts
  • packages/prisma-next/src/execution/operators.ts
  • packages/prisma-next/src/execution/parameterized.ts
  • packages/prisma-next/src/execution/routing.ts
  • packages/prisma-next/src/exports/column-types.ts
  • packages/prisma-next/src/exports/control.ts
  • packages/prisma-next/src/exports/middleware.ts
  • packages/prisma-next/src/exports/migration.ts
  • packages/prisma-next/src/exports/runtime.ts
  • packages/prisma-next/src/exports/stack.ts
  • packages/prisma-next/src/extension-metadata/codec-metadata.ts
  • packages/prisma-next/src/extension-metadata/constants.ts
  • packages/prisma-next/src/extension-metadata/descriptor-meta.ts
  • packages/prisma-next/src/middleware/bulk-encrypt.ts
  • packages/prisma-next/src/migration/call-classes.ts
  • packages/prisma-next/src/migration/cipherstash-codec.ts
  • packages/prisma-next/src/migration/codec-hooks-factory.ts
  • packages/prisma-next/src/migration/eql-bundle.ts
  • packages/prisma-next/src/stack/derive-schemas.ts
  • packages/prisma-next/src/stack/from-stack-v3.ts
  • packages/prisma-next/src/stack/from-stack.ts
  • packages/prisma-next/src/stack/sdk-adapter.ts
  • packages/prisma-next/src/types/codec-types.ts
  • packages/prisma-next/src/types/operation-types.ts
  • packages/prisma-next/src/v3/bulk-encrypt-v3.ts
  • packages/prisma-next/src/v3/envelope-number.ts
  • packages/prisma-next/test/abort.test.ts
  • packages/prisma-next/test/authoring.test.ts
  • packages/prisma-next/test/bulk-encrypt-middleware.helpers.ts
  • packages/prisma-next/test/bulk-encrypt-middleware.test.ts
  • packages/prisma-next/test/bundling-isolation.test.ts
  • packages/prisma-next/test/call-classes.test.ts
  • packages/prisma-next/test/call-classes.types.test-d.ts
  • packages/prisma-next/test/cipherstash-codec-numeric.test.ts
  • packages/prisma-next/test/cipherstash-codec-other-codecs.test.ts
  • packages/prisma-next/test/cipherstash-codec-string.test.ts
  • packages/prisma-next/test/cipherstash-codec.test.ts
  • packages/prisma-next/test/codec-runtime.test.ts
  • packages/prisma-next/test/column-types.test.ts
  • packages/prisma-next/test/decrypt-all.test.ts
  • packages/prisma-next/test/derive-schemas.test.ts
  • packages/prisma-next/test/descriptor.test.ts
  • packages/prisma-next/test/envelope-double.test.ts
  • packages/prisma-next/test/equality-trait-removal.test.ts
  • packages/prisma-next/test/from-stack-divergence.test.ts
  • packages/prisma-next/test/helpers.test.ts
  • packages/prisma-next/test/helpers.types.test-d.ts
  • packages/prisma-next/test/live/side-by-side-clients-live-pg.test.ts
  • packages/prisma-next/test/operation-types.types.test-d.ts
  • packages/prisma-next/test/operator-lowering-equality.test.ts
  • packages/prisma-next/test/operator-lowering-order-range.test.ts
  • packages/prisma-next/test/operator-lowering-text-search.test.ts
  • packages/prisma-next/test/operator-lowering.helpers.ts
  • packages/prisma-next/test/operator-lowering.test.ts
  • packages/prisma-next/test/psl-interpretation-numeric.test.ts
  • packages/prisma-next/test/psl-interpretation-other-types.test.ts
  • packages/prisma-next/test/psl-interpretation.test.ts
  • packages/prisma-next/test/runtime-descriptor.test.ts
  • packages/prisma-next/test/sdk-adapter.test.ts
  • packages/prisma-next/test/v3/bulk-encrypt-v3.test.ts
  • packages/prisma-next/test/v3/constants-v3.test.ts
  • packages/prisma-next/test/v3/envelope-number.test.ts
  • packages/prisma-next/test/v3/migration-v3.test.ts
  • packages/prisma-next/test/v3/operator-gating-v3.test.ts
  • packages/prisma-next/test/v3/properties.test.ts
  • packages/prisma-next/test/v3/runtime-v3.test.ts
  • packages/prisma-next/tsup.config.ts
  • skills/stash-prisma-next/SKILL.md
💤 Files with no reviewable changes (48)
  • packages/prisma-next/migrations/20260601T0000_install_eql_bundle/migration.json
  • packages/prisma-next/test/from-stack-divergence.test.ts
  • packages/prisma-next/test/cipherstash-codec-numeric.test.ts
  • packages/prisma-next/test/helpers.test.ts
  • packages/prisma-next/src/migration/eql-bundle.ts
  • packages/prisma-next/test/operator-lowering-order-range.test.ts
  • packages/prisma-next/test/cipherstash-codec.test.ts
  • packages/prisma-next/migrations/20260601T0000_install_eql_bundle/migration.ts
  • packages/prisma-next/src/exports/middleware.ts
  • packages/prisma-next/src/execution/envelope-double.ts
  • packages/prisma-next/src/exports/migration.ts
  • packages/prisma-next/test/call-classes.types.test-d.ts
  • packages/prisma-next/test/sdk-adapter.test.ts
  • packages/prisma-next/test/derive-schemas.test.ts
  • packages/prisma-next/test/operator-lowering-text-search.test.ts
  • packages/prisma-next/test/operator-lowering-equality.test.ts
  • packages/prisma-next/migrations/20260601T0000_install_eql_bundle/end-contract.json
  • examples/prisma/src/db.ts
  • packages/prisma-next/src/execution/codec-runtime.ts
  • packages/prisma-next/test/bulk-encrypt-middleware.test.ts
  • packages/prisma-next/test/runtime-descriptor.test.ts
  • packages/prisma-next/test/psl-interpretation-other-types.test.ts
  • packages/prisma-next/src/migration/call-classes.ts
  • packages/prisma-next/test/envelope-double.test.ts
  • packages/prisma-next/test/operator-lowering.test.ts
  • packages/prisma-next/src/stack/sdk-adapter.ts
  • packages/prisma-next/test/psl-interpretation-numeric.test.ts
  • packages/prisma-next/src/stack/from-stack.ts
  • packages/prisma-next/migrations/20260601T0000_install_eql_bundle/end-contract.d.ts
  • packages/prisma-next/test/operator-lowering.helpers.ts
  • packages/prisma-next/test/helpers.types.test-d.ts
  • packages/prisma-next/test/codec-runtime.test.ts
  • packages/prisma-next/src/execution/parameterized.ts
  • packages/prisma-next/tsup.config.ts
  • packages/prisma-next/src/execution/cell-codec-factory.ts
  • packages/prisma-next/src/execution/helpers.ts
  • packages/prisma-next/test/cipherstash-codec-string.test.ts
  • packages/prisma-next/test/live/side-by-side-clients-live-pg.test.ts
  • packages/prisma-next/src/middleware/bulk-encrypt.ts
  • packages/prisma-next/src/execution/operators.ts
  • packages/prisma-next/test/cipherstash-codec-other-codecs.test.ts
  • packages/prisma-next/test/call-classes.test.ts
  • packages/prisma-next/src/migration/codec-hooks-factory.ts
  • packages/prisma-next/test/v3/constants-v3.test.ts
  • packages/prisma-next/src/migration/cipherstash-codec.ts
  • packages/prisma-next/test/column-types.test.ts
  • packages/prisma-next/src/stack/derive-schemas.ts
  • packages/prisma-next/src/exports/column-types.ts

Comment thread packages/prisma-next/README.md Outdated
… stale docs

James's review (#712) and CodeRabbit.

Wire the "middleware not wired" diagnostic on the v3 write path.
`isBulkEncryptMiddlewareRegistered` was marked-but-never-read: the read
site lived in the v2 `cell-codec-factory.ts`, deleted in this PR, and v3
never had one. Port it to `CipherstashV3CellCodec#encode` so an SDK with
no `bulkEncryptMiddlewareV3(sdk)` registered fails fast with
`RUNTIME.ENCODE_FAILED` and a copy-pasteable wiring snippet instead of an
opaque pg serialise error. Memoised per codec (the registry is add-only),
so it costs one WeakSet lookup rather than one per cell.

Docs and comments naming removed symbols:

- README: drop the "legacy v2 surface keeps its `cipherstash*` names"
  clause, and switch the query example from `cipherstashIlike` to
  `eqlMatch`. The LIKE wildcard goes too — `eqlMatch` is bloom
  token containment (`eql_v3.contains`), not SQL `LIKE`, so
  `"%@example.com"` would have been misleading.
- migration.ts: the trailing rationale still said "invariant-only
  self-edge" after the edge was re-rooted as genesis.
- runtime-v3.ts: referenced the removed `createCipherstashRuntimeDescriptor`,
  and described a v2/v3 co-registration constraint that no longer exists.
- operator-gating-v3.test.ts: header claimed to pin v2/v3 method-name
  disjointness; the body now pins the `eql*` prefix instead.
- from-stack-v3.test.ts: described `cipherstashFromStackV2` as "separate,
  untouched" when it was removed outright.
- DEVELOPING.md: said the v3 codec raises no wiring diagnostic — now it does.

320 -> 322 unit tests (both new cases cover the diagnostic: it fires for an
unregistered SDK, and stays silent for an already-encrypted envelope).
Typecheck, build, and biome clean.
@coderdan

Copy link
Copy Markdown
Contributor Author

Thanks both — all review points addressed in 9314afb.

@freshtonic

  1. Dead registry — fixed properly rather than deferred. Ported the v2 guard from the deleted cell-codec-factory.ts into CipherstashV3CellCodec#encode. An SDK with no bulkEncryptMiddlewareV3(sdk) registered now fails with RUNTIME.ENCODE_FAILED and a copy-pasteable wiring snippet instead of an opaque pg serialise error. Memoised per codec (the registry is add-only), so it costs one WeakSet lookup, not one per encoded cell. Two new tests: the diagnostic fires for an unregistered SDK, and stays silent for an already-encrypted envelope (which needs no second pass). DEVELOPING.md, the changeset, and the PR body are updated — the registry is live, not dead weight.

  2. Two stale doc comments — fixed, plus a third. runtime-v3.ts and from-stack-v3.test.ts as you flagged. Sweeping for the same class turned up operator-gating-v3.test.ts, whose header still claimed to pin v2/v3 method-name disjointness — the body had already been rewritten to pin the eql* prefix instead. The only surviving mentions of removed symbols are now in .changeset/ and docs/superpowers/, where they correctly describe the removal.

  3. Commit granularity — noted, no action.

@coderabbitai

  • README line 13 — dropped the "legacy v2 surface keeps its cipherstash* names" clause.
  • README line 81 — cipherstashIlikeeqlMatch. Also dropped the % wildcards: eqlMatch lowers to eql_v3.contains (bloom token containment), so "%@example.com" implied LIKE semantics the operator does not have. Now eqlMatch("example.com"), matching the skill and examples/prisma.
  • migration.ts — retired the trailing "invariant-only self-edge" wording for the genesis framing.

CI: the db=supabase job on this PR was cancelled, not failed — so the Supabase variant, the exact thing this PR fixes, had never actually run. Re-ran it and it passes. Root cause is unrelated to this PR: the three integration workflows share the job-level concurrency group integration-live-db-<db>, and GitHub allows only one in-progress + one pending run per group, so any third contender is cancelled outright (four cancellations in ~80 minutes on 2026-07-20). Fix going up as a separate PR.

Validation: 322/322 unit tests, typecheck clean, build clean, 0 biome errors.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@coderdan Thanks for the thorough follow-up. The README now accurately reflects eqlMatch’s containment semantics, and the migration terminology correctly describes the v3-only genesis edge. Glad the rerun confirmed the Supabase path passes as well.

🐇✅


✏️ Learnings added
Learnt from: coderdan
URL: https://github.com/cipherstash/stack/pull/712

Timestamp: 2026-07-21T03:05:08.604Z
Learning: The repository’s integration workflows share a job-level GitHub Actions concurrency group named `integration-live-db-<db>`. GitHub permits only one in-progress and one pending job per group, so a third contender can be cancelled; such cancellations are infrastructure scheduling behavior rather than test failures. The Supabase integration variant for PR `#712` was rerun and passed.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

@coderdan
coderdan merged commit 2e6f032 into main Jul 21, 2026
13 of 14 checks passed
@coderdan
coderdan deleted the fix/prisma-next-v3-only-install branch July 21, 2026 03:08
coderdan added a commit that referenced this pull request Jul 21, 2026
…731)

* ci(integration): isolate live-DB stacks instead of serialising them

Integration jobs were being CANCELLED, not run — four times in ~80 minutes
on 2026-07-20, most recently the `db=supabase` leg of #712, which is the
exact variant that PR exists to fix.

Cause: the three integration workflows share one job-level concurrency
group, `integration-live-db-<db>`, deliberately not scoped by ref
(d02bf63) because two PRs contend for a fixed host port as much as two
pushes to one PR. But GitHub Actions allows only ONE in-progress plus ONE
pending run per group — a third contender is cancelled outright. With
three workflows funnelling into two keys, that fires under any load.

The failure mode is worse than a flake: a cancelled job never runs, so
its check goes ABSENT rather than red. The signal is silently lost, and
`main` is not branch-protected, so nothing blocks the merge.

Remove the contention rather than serialising it. A new `integration-db`
composite action gives every job:

  - its own compose project name (run id + attempt + job + variant), so
    container names cannot collide; and
  - EPHEMERAL host ports — `CS_PG_PORTS` / `CS_PGRST_PORTS` carry a bare
    container port, so compose publishes with no fixed host side and the
    assigned port is read back with `docker compose port`.

Nothing is shared between jobs, so nothing needs to queue, and the
concurrency groups are gone from all three workflows. The compose files
keep their fixed 55432 / 55433 / 55430 mappings when the vars are unset,
so local dev and the help text in `test-kit/src/env.ts` are unchanged.

Dropped the pre-`up` `docker compose down` too. With unique project names
it is a no-op, and blanket-pruning is now actively unsafe: without the
concurrency group, another job's stack may be live on the same runner.

Also, since this adds a composite action: `.github/actions/` had no
CODEOWNERS rule, though such actions run arbitrary steps in the same job
with the same secrets as the workflow calling them. Added the rule and
the matching assertion in `supply-chain.e2e.test.ts` (verified it fails
without it). Fixed a stale claim in the Drizzle workflow header that
`PGRST_URL` is left unset — the matrix had been setting it.

Verified: compose interpolation resolves to the fixed mapping by default
and to an ephemeral publish under the CI vars (`docker compose config`);
YAML parses; the action's shell body is syntax-clean with no GitHub
templating interpolated into it; 18/18 supply-chain e2e tests pass.

* fix(ci): validate every port readback, not just Postgres

CodeRabbit caught a real asymmetry in the new action: `pg_port` was checked
for emptiness but the supabase branch built `pgrest_url` straight from
`$(port_of postgrest 3000)`. `docker compose port` exits 0 with EMPTY
stdout when a port is not bound, so an unbound PostgREST would have
silently yielded `http://localhost:` and handed every `PGRST_URL` consumer
(the Drizzle-supabase leg, both Supabase-workflow steps) a malformed URL
instead of the immediate error the Postgres path already gave.

Move the check into `port_of` itself so it applies by construction and the
asymmetry cannot come back, rather than adding a second call-site guard.
Each port is now captured in its own bare assignment so `set -e` fails the
step unambiguously on a non-zero `port_of`.

Verified with a stubbed `docker` that returns a port for `db` and nothing
for `postgrest`: the Postgres read succeeds, the guard fires for postgrest,
and the script exits 1 before exporting anything.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

prisma-next: make the adapter EQL v3-only — stop installing the EQL v2 baseline (F3, Supabase superuser block)

2 participants